<?php

namespace Common\Middleware\Jwt;

use Common\Context\WebsocketContext;
use Common\Helpers\DebugHelper;
use Common\Libs\Jwt\Jwt;
use Hyperf\Context\ApplicationContext;
use Hyperf\Context\Context;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Contract\ContainerInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
use Hyperf\HttpServer\Router\Dispatched;
use Hyperf\HttpServer\Router\DispatcherFactory;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class JwtMiddleware implements MiddlewareInterface
{
    /**
     * @var ContainerInterface
     */
    #[Inject]
    protected ContainerInterface $container;

    /**
     * @var RequestInterface
     */
    #[Inject]
    protected RequestInterface $request;

    /**
     * @var HttpResponse
     */
    #[Inject]
    protected HttpResponse $response;

    /**
     * @Inject(DispatcherFactory::class)
     * @var DispatcherFactory
     */
    #[Inject]
    protected DispatcherFactory $dispatcherFactory;

    /**
     * @param ServerRequestInterface $request
     * @param RequestHandlerInterface $handler
     * @return ResponseInterface
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        DebugHelper::consoleWrite('jwt校验开始');

        try {
            $data = WebsocketContext::get(WebsocketContext::CONTENT);
            DebugHelper::consoleWrite('jwt-data');
            $request = Context::get(ServerRequestInterface::class,$data);
            if (empty($request->getAttribute(Dispatched::class)->handler)){
                return $this->response->json([
                    'code' => 401,
                    'message' => '非法请求',
                    'data' => []
                ]);
            }
            $bbb = $this->request->getBody();
            var_dump($bbb);
            $callback = $request->getAttribute(Dispatched::class)->handler->callback;

            if(!empty($data)) {
                $token = $data['accessToken'];
                DebugHelper::consoleWrite('jwt中间件-action处理', $callback);

                [$class, $action] = strrpos($callback, '@') ? explode('@', $callback) : [$callback, 'index'];
                $controller = new $class($this->request, $this->response);
                DebugHelper::consoleWrite('action处理', [
                    'controller' => $controller
                ]);


                //为空都需要，在列表排除
                if (empty($controller->authOptional) || !in_array($action, $controller->authOptional)) {
                    if (empty($token)) {
                        return $this->response->json([
                            'code' => 401,
                            'message' => 'Token is missing',
                            'data' => []
                        ]);
                    }

                    /**
                     * @var ConfigInterface $config
                     */
                    $config = ApplicationContext::getContainer()->get(ConfigInterface::class);

                    // 验证 JWT 是否合法
                    $secret = $config->get('jwt.SecretKey');
                    $tokenStr = \Common\Services\JwtService::decrypt_ecb($token);
                    $jwtObject = Jwt::getInstance()->setSecretKey($secret)->decode($tokenStr);

                    $status = $jwtObject->getStatus();

                    $Iss = $jwtObject->getIss();

                    if ($Iss != $config->get('jwt.Iss')) {
                        return $this->response->json([
                            'code' => 401,
                            'message' => '非法请求',
                            'data' => []
                        ]);
                    }

                    // 如果encode设置了秘钥,decode 的时候要指定
                    switch ($status) {
                        case  1:
                            $userInfo = \Common\Services\JwtService::getUser($token);
                            DebugHelper::consoleWrite('挂载前数据', $userInfo['member']);
                            // 挂载数据 到 $request 对象上
                            $request = $request->withAttribute('userInfo', $userInfo)
                                ->withAttribute('member_id', $userInfo['member']['member_id'])
                                ->withAttribute('member', $userInfo['member']);

                            break;
                        case  -1:
                            return $this->response->json([
                                'code' => 402,
                                'message' => 'token已失效'
                            ]);
                        case  -2:
                            return $this->response->json([
                                'code' => 403,
                                'message' => 'token已过期'
                            ]);
                    }
                }
                Context::set(ServerRequestInterface::class, $request);
            }
            return $handler->handle($request);
        } catch (\Exception $e) {
            $trace = $e->getTrace()[0];
            $file = $trace['file'];
            $line = $trace['line'];
            // JWT 验证失败，返回未授权响应
            return $this->response->json([
                'code' => 402,
                'message' => $e->getMessage(),
                'data' =>$e->getTrace()
            ]);
        } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) {

            return $this->response->json([
                'code' => 402,
                'message' => $e->getMessage(),
                'data' => $e->getTrace()
            ]);
        }
    }
}